/*
*********************************
*@version: 1.0
*@date: 2022/4/28 16:18
1.登录成功后，返回token
2.否则登录失败
*********************************
*/
package hanlder

import (
	"encoding/json"
	"fmt"
	"groudserver/db"
	"io"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/sirupsen/logrus"
)

const (
	SECRETKEY = "202203021124355WJ" //私钥
	MAXAGE    = 60 * 60 * 24        //秘钥有效期
)

// 自定义 Claims
type CustomClaims struct {
	jwt.StandardClaims
}

func (pv *loginHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var auth db.Auth
	var result Response
	var msg db.UserInfo
	if r.Method != "POST" {
		result = GetCode(405)
	}
	body, err := ioutil.ReadAll(r.Body)
	if err != nil && err != io.EOF {
		logrus.Error("处理信息 err:", err.Error(), "信息请求处理消息体：", string(body))
		result = GetCode(400)
	} else {
		if err := json.Unmarshal(body, &auth); err != nil {
			logrus.Error("解析失败：", err.Error())
			result = GetCode(406)
		} else {
			logrus.Info("登录用户名", auth.UserName, "密码:", auth.Password)
		}
	}
	logrus.Info("用户名 user:", auth.UserName, "密码 password", auth.Password)
	spl := "select count(*) from " + Ptv.DataBase.TableUser + " where username ='" + auth.UserName + "' and password = '" + auth.Password + "'"
	check := db.CheckUser(spl)

	if check {
		token, createtime := GetToken(auth.UserName)
		if token == "" && createtime == 0 {
			result.Msg = "Authentication failed"
			result.Code = 401
			result.Token = token
		} else {
			result.Msg = "login success"
			result.Code = 200
			result.Token = token

			//将用户信息插入数据库
			msg.UserName = auth.UserName
			msg.Token = token
			msg.CreateTime = createtime
			err := db.InsertUserInfo(msg)
			if err != nil {
				logrus.Error("用户信息插入数据库失败")
			}
		}

	} else {
		//判断用户名密码是否错误
		result.Msg = "username or password error"
		result.Code = 400
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	//跨域头
	w.Header().Set("Access-Control-Allow-Methods", "*")
	w.Header().Set("Access-Control-Allow-Headers", "*")
	if err := json.NewEncoder(w).Encode(result); err != nil {
		logrus.Fatal(err)
	}
}

// 获取token
func GetToken(user string) (tokes string, createtime int64) {
	customClaims := &CustomClaims{
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(time.Duration(MAXAGE) * time.Second).Unix(), // 过期时间，必须设置
			Issuer:    user,                                                       // 非必须，也可以填充用户名，
		},
	}
	//采用HMAC SHA256 加密算法
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, customClaims)
	tokenString, err := token.SignedString([]byte(SECRETKEY))
	if err != nil {
		logrus.Error(err)
		return "", 0
	}
	logrus.Info("Token:  ", tokenString)
	//解析token
	ret, err := ParseToken(tokenString)
	if err != nil {
		return "", 0
	}
	logrus.Printf("userInfo:%v", ret)
	return tokenString, ret.ExpiresAt
}

// 解析token
func ParseToken(tokenString string) (*CustomClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return []byte(SECRETKEY), nil
	})
	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
		return claims, nil
	} else {
		return nil, err
	}
}

// 状态码信息设置
func GetCode(code int) Response {
	var res Response
	if code == 200 {
		res.Code = 200
		res.Msg = "success"
	} else if code == 400 {
		res.Code = 400
		res.Msg = "bad request"
	} else if code == 404 {
		res.Code = 404
		res.Msg = "not found resource"
	} else if code == 405 {
		res.Code = 405
		res.Msg = "method not allowed"
	} else if code == 406 {
		res.Code = 406
		res.Msg = "not acceptable"
	}
	return res
}

// 获取用户信息
func (pv *getUserInfoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	logrus.Info("获取用户信息信息头:", r.Header.Get("token"))
	var res RespEx
	var sql string
	var result *db.UserInfoEx
	var ret bool
	if r.Method != "GET" {
		res = GetStatusCodeEx(405)
	}
	if r.RequestURI == "" {
		res = GetStatusCodeEx(406)
	}
	if len(r.Header.Get("token")) <= 0 {
		res = GetStatusCodeEx(203)
	} else if len(r.Header.Get("token")) > 0 && r.Header.Get("token") != "" {
		token := r.Header.Get("token")
		sql = "select id, username,  createtime from " + Ptv.DataBase.UserInfoTbl + " where token = " + "'" + token + "'"
		result, ret = db.GetUserInfo(sql)
		logrus.Info("数据库查询语句:", sql, "CreateTime：", result.CreateTime, "查询结果:", ret)
		if ret != false && result.CreateTime > 0 { //如果数据长度大于0, 则说明查询成功
			res.Code = 200
			res.Msg = "success"
			res.Data = result
		} else if ret != false && result.CreateTime <= 0 {
			res = GetStatusCodeEx(201)
		} else if ret == false && result.CreateTime <= 0 {
			res = GetStatusCodeEx(203)
		} else {
			res = GetStatusCodeEx(202)
		}

	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	//跨域头
	w.Header().Set("Access-Control-Allow-Methods", "*")
	w.Header().Set("Access-Control-Allow-Headers", "*")
	if err := json.NewEncoder(w).Encode(res); err != nil {
		logrus.Fatal(err)
	}
}
